/*
 * Copyright (C) 2014 Evgeniy Egorov
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ru.apertum.qsystem.client.forms;

import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.embed.swing.JFXPanel;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.input.TouchEvent;
import javafx.scene.layout.Region;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebHistory;
import javafx.scene.web.WebView;
import lombok.extern.log4j.Log4j2;
import org.jdesktop.application.Application;
import org.jdesktop.application.ResourceMap;
import ru.apertum.qsystem.QSystem;
import ru.apertum.qsystem.client.QProperties;
import ru.apertum.qsystem.client.common.WelcomeParams;
import ru.apertum.qsystem.client.model.QPanel;
import ru.apertum.qsystem.common.ATalkingClock;
import ru.apertum.qsystem.common.QConfig;
import ru.apertum.qsystem.common.Uses;
import ru.apertum.qsystem.server.model.QProperty;

import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.LayoutStyle;
import javax.swing.border.BevelBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.MatteBorder;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.image.MemoryImageSource;
import java.io.IOException;
import java.util.Objects;
import java.util.ResourceBundle;


/**
 * Диалогоаое окно отображения вэб контента по урлу.
 *
 * @author Evgeniy Egorov
 */
@SuppressWarnings({"squid:S1192", "squid:S1172", "squid:S1450", "squid:S1604", "squid:S1161", "squid:MaximumInheritanceDepth"})
@Log4j2
public class FInfoDialogWeb extends javax.swing.JDialog {

    private final JFXPanel javafxPanel;

    /**
     * Creates new form FInfoDialogWeb.
     */
    public FInfoDialogWeb(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();

        javafxPanel = new JFXPanel();
        javafxPanel.setOpaque(false);
        javafxPanel.setBorder(new BevelBorder(BevelBorder.RAISED));
        javafxPanel.setLayout(new GridLayout(1, 1));
        final GridLayout gl = new GridLayout(1, 1);
        panel.setLayout(gl);
        panel.add(javafxPanel, BorderLayout.CENTER);

        Platform.runLater(() -> {
            bro = new Browser();
            Scene scene = new Scene(bro, 750, 500, javafx.scene.paint.Color.web("#666970"));
            javafxPanel.setScene(scene);
        });
        if (WelcomeParams.getInstance().btnFont != null) {
            btnBack.setFont(WelcomeParams.getInstance().btnFont);
            btnClose.setFont(WelcomeParams.getInstance().btnFont);
            btnForward.setFont(WelcomeParams.getInstance().btnFont);
            btnHome.setFont(WelcomeParams.getInstance().btnFont);
        }
        if (QConfig.cfg().isWelcomeFeedback()) {
            btnClose.setVisible(false);
        }
        final QProperty cmd = QProperties.get().getProperty(QProperties.SECTION_WELCOME, "keyboard_cmd");
        btnKeyboard.setVisible(cmd != null);
    }

    private static Browser bro;
    private static Long result = null;
    private static int delay = 10000;
    private static FInfoDialogWeb infoDialogWeb;

    private static ResourceMap localeMap = null;

    private static String getLocaleMessage(String key) {
        if (localeMap == null) {
            localeMap = Application.getInstance(QSystem.class).getContext().getResourceMap(FInfoDialog.class);
        }
        return localeMap.getString(key);
    }

    private void btnKeyboardActionPerformed(ActionEvent e) {
        try {
            String cmd = QProperties.get().getProperty(QProperties.SECTION_WELCOME, "keyboard_cmd", "cmd /c osk");
            Runtime.getRuntime().exec(cmd);
        } catch (IOException ex) {
            log.error("Runtime exec error", ex);
        }
    }

    /**
     * Статический метод который показывает модально диалог чтения информации.
     *
     * @param parent     фрейм относительно которого будет модальность
     * @param modal      модальный диалог или нет
     * @param fullscreen растягивать форму на весь экран и прятать мышку или нет
     * @param delay      задержка перед скрытием диалога. если 0, то нет автозакрытия диалога
     * @param url        ресурс с контентом для показа.
     * @return XML-описание результата предварительной записи, по сути это номерок. если null, то отказались от предварительной записи
     */
    public static Long showInfoDialogWeb(Frame parent, boolean modal, boolean fullscreen, int delay, String url) {
        FInfoDialogWeb.delay = delay;
        log.info("Чтение WEB информации");

        if (infoDialogWeb == null) {
            infoDialogWeb = new FInfoDialogWeb(parent, modal);
            infoDialogWeb.setTitle(getLocaleMessage("dialog.title"));
        }

        Platform.runLater(() -> bro.load(url));

        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            log.warn("Interrupted!", ex);
            // Restore interrupted state...
            Thread.currentThread().interrupt();
        }

        FInfoDialogWeb.result = null;
        Uses.setLocation(infoDialogWeb);
        if (!(QConfig.cfg().isDebug() || QConfig.cfg().isDemo() && !fullscreen)) {
            Uses.setFullSize(infoDialogWeb);
            if (QConfig.cfg().isHideCursor()) {
                int[] pixels = new int[16 * 16];
                Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(16, 16, pixels, 0, 16));
                Cursor transparentCursor = Toolkit.getDefaultToolkit().createCustomCursor(image, new Point(0, 0), "invisibleCursor");
                infoDialogWeb.setCursor(transparentCursor);
            }
        } else {
            infoDialogWeb.setSize(FWelcome.getScreenHorizontal(), FWelcome.getScreenVertical());
            Uses.setLocation(infoDialogWeb, parent);
        }

        if (infoDialogWeb.clockBack.isActive()) {
            infoDialogWeb.clockBack.stop();
        }
        if (infoDialogWeb.clockBack.getInterval() > 1000) {
            infoDialogWeb.clockBack.start();
        }

        infoDialogWeb.setVisible(true);
        return result;
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    // Generated using JFormDesigner non-commercial license
    private void initComponents() {
        ResourceBundle bundle = ResourceBundle.getBundle("ru.apertum.qsystem.client.forms.resources.FInfoDialogWeb");
        qPanel1 = new QPanel(WelcomeParams.getInstance().getBackgroundImg("infoweb"));
        ;
        qPanel2 = new QPanel();
        btnClose = new JButton();
        btnForward = new JButton();
        btnBack = new JButton();
        btnHome = new JButton();
        btnKeyboard = new JButton();
        panel = new QPanel();

        //======== this ========
        setName("Form");
        setUndecorated(true);
        var contentPane = getContentPane();

        //======== qPanel1 ========
        {
            qPanel1.setName("qPanel1");

            //======== qPanel2 ========
            {
                qPanel2.setBorder(new MatteBorder(1, 1, 1, 1, Color.black));
                qPanel2.setName("qPanel2");
                qPanel2.setOpaque(false);

                //---- btnClose ----
                btnClose.setText(bundle.getString("btnClose.text"));
                btnClose.setBorder(new CompoundBorder(
                        new BevelBorder(BevelBorder.RAISED),
                        new BevelBorder(BevelBorder.RAISED)));
                btnClose.setName("btnClose");
                btnClose.setFont(new Font("Tahoma", Font.PLAIN, 36));
                btnClose.setIcon(new ImageIcon(getClass().getResource("/ru/apertum/qsystem/client/forms/resources/stop.png")));
                btnClose.addActionListener(e -> btnCloseActionPerformed(e));

                //---- btnForward ----
                btnForward.setText(bundle.getString("btnForward.text"));
                btnForward.setToolTipText(bundle.getString("btnForward.toolTipText"));
                btnForward.setBorder(new CompoundBorder(
                        new BevelBorder(BevelBorder.RAISED),
                        new BevelBorder(BevelBorder.RAISED)));
                btnForward.setName("btnForward");
                btnForward.setIcon(new ImageIcon(getClass().getResource("/ru/apertum/qsystem/client/forms/resources/forwardPage.png")));
                btnForward.addActionListener(e -> btnForwardActionPerformed(e));

                //---- btnBack ----
                btnBack.setText(bundle.getString("btnBack.text"));
                btnBack.setBorder(new CompoundBorder(
                        new BevelBorder(BevelBorder.RAISED),
                        new BevelBorder(BevelBorder.RAISED)));
                btnBack.setName("btnBack");
                btnBack.setIcon(new ImageIcon(getClass().getResource("/ru/apertum/qsystem/client/forms/resources/backPage.png")));
                btnBack.addActionListener(e -> btnBackActionPerformed(e));

                //---- btnHome ----
                btnHome.setText(bundle.getString("btnHome.text"));
                btnHome.setBorder(new CompoundBorder(
                        new BevelBorder(BevelBorder.RAISED),
                        new BevelBorder(BevelBorder.RAISED)));
                btnHome.setName("btnHome");
                btnHome.setIcon(new ImageIcon(getClass().getResource("/ru/apertum/qsystem/client/forms/resources/serv_btn.png")));
                btnHome.addActionListener(e -> btnHomeActionPerformed(e));

                //---- btnKeyboard ----
                btnKeyboard.setText(bundle.getString("FInfoDialogWeb.btnKeyboard.text"));
                btnKeyboard.setBorder(new CompoundBorder(
                        new BevelBorder(BevelBorder.RAISED),
                        new BevelBorder(BevelBorder.RAISED)));
                btnKeyboard.setIcon(new ImageIcon(getClass().getResource("/ru/apertum/qsystem/client/forms/resources/keyboard.png")));
                btnKeyboard.setName("btnKeyboard");
                btnKeyboard.addActionListener(e -> btnKeyboardActionPerformed(e));

                GroupLayout qPanel2Layout = new GroupLayout(qPanel2);
                qPanel2.setLayout(qPanel2Layout);
                qPanel2Layout.setHorizontalGroup(
                        qPanel2Layout.createParallelGroup()
                                .addGroup(qPanel2Layout.createSequentialGroup()
                                        .addContainerGap()
                                        .addComponent(btnClose, GroupLayout.PREFERRED_SIZE, 280, GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 147, Short.MAX_VALUE)
                                        .addComponent(btnKeyboard, GroupLayout.PREFERRED_SIZE, 147, GroupLayout.PREFERRED_SIZE)
                                        .addGap(18, 18, 18)
                                        .addComponent(btnHome, GroupLayout.PREFERRED_SIZE, 147, GroupLayout.PREFERRED_SIZE)
                                        .addGap(18, 18, 18)
                                        .addComponent(btnBack, GroupLayout.PREFERRED_SIZE, 147, GroupLayout.PREFERRED_SIZE)
                                        .addGap(18, 18, 18)
                                        .addComponent(btnForward, GroupLayout.PREFERRED_SIZE, 147, GroupLayout.PREFERRED_SIZE)
                                        .addContainerGap())
                );
                qPanel2Layout.setVerticalGroup(
                        qPanel2Layout.createParallelGroup()
                                .addGroup(GroupLayout.Alignment.TRAILING, qPanel2Layout.createSequentialGroup()
                                        .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addGroup(qPanel2Layout.createParallelGroup(GroupLayout.Alignment.TRAILING)
                                                .addComponent(btnKeyboard, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE)
                                                .addGroup(qPanel2Layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                                                        .addComponent(btnForward, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE)
                                                        .addComponent(btnBack, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE)
                                                        .addComponent(btnHome, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE))
                                                .addComponent(btnClose, GroupLayout.PREFERRED_SIZE, 70, GroupLayout.PREFERRED_SIZE))
                                        .addContainerGap())
                );
            }

            //======== panel ========
            {
                panel.setBorder(new MatteBorder(1, 1, 1, 1, Color.black));
                panel.setName("panel");

                GroupLayout panelLayout = new GroupLayout(panel);
                panel.setLayout(panelLayout);
                panelLayout.setHorizontalGroup(
                        panelLayout.createParallelGroup()
                                .addGap(0, 0, Short.MAX_VALUE)
                );
                panelLayout.setVerticalGroup(
                        panelLayout.createParallelGroup()
                                .addGap(0, 542, Short.MAX_VALUE)
                );
            }

            GroupLayout qPanel1Layout = new GroupLayout(qPanel1);
            qPanel1.setLayout(qPanel1Layout);
            qPanel1Layout.setHorizontalGroup(
                    qPanel1Layout.createParallelGroup()
                            .addComponent(qPanel2, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(panel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
            );
            qPanel1Layout.setVerticalGroup(
                    qPanel1Layout.createParallelGroup()
                            .addGroup(GroupLayout.Alignment.TRAILING, qPanel1Layout.createSequentialGroup()
                                    .addComponent(panel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                    .addGap(0, 0, 0)
                                    .addComponent(qPanel2, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
            );
        }

        GroupLayout contentPaneLayout = new GroupLayout(contentPane);
        contentPane.setLayout(contentPaneLayout);
        contentPaneLayout.setHorizontalGroup(
                contentPaneLayout.createParallelGroup()
                        .addComponent(qPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        contentPaneLayout.setVerticalGroup(
                contentPaneLayout.createParallelGroup()
                        .addComponent(qPanel1, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
        );
        pack();
        setLocationRelativeTo(getOwner());
    }// </editor-fold>//GEN-END:initComponents

    private void btnCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCloseActionPerformed
        result = null;
        Platform.runLater(() ->
                bro.webEngine.loadContent("<html><table width=100% height=100% align='center'><tr><td width=100% height=100% align='center'>"
                        + "<p style=\"font-size:80px;color:blue\">Opening...</p>"
                        + "</td></tr></table></html>")
        );
        if (clockBack.isActive()) {
            clockBack.stop();
        }
        setVisible(false);
    }//GEN-LAST:event_btnCloseActionPerformed

    private void btnForwardActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnForwardActionPerformed
        bro.goForward();
    }//GEN-LAST:event_btnForwardActionPerformed

    private void btnBackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBackActionPerformed
        bro.goBack();
    }//GEN-LAST:event_btnBackActionPerformed

    private void btnHomeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnHomeActionPerformed
        bro.reload();
    }//GEN-LAST:event_btnHomeActionPerformed

    /**
     * Таймер, по которому будем выходить в корень меню.
     */
    private final transient ATalkingClock clockBack = new ATalkingClock(delay, 1) {

        @Override
        public void run() {
            if (!QConfig.cfg().isWelcomeFeedback()) {
                setVisible(false);
            }
        }
    };

    // Variables declaration - do not modify//GEN-BEGIN:variables
    // Generated using JFormDesigner non-commercial license
    private QPanel qPanel1;
    private QPanel qPanel2;
    private JButton btnClose;
    private JButton btnForward;
    private JButton btnBack;
    private JButton btnHome;
    private JButton btnKeyboard;
    private QPanel panel;
    // End of variables declaration//GEN-END:variables

    static class Browser extends Region {

        private final WebView webView = new WebView();
        private final WebEngine webEngine = webView.getEngine();

        public Browser() {

            try {
                webView.getEngine().setUserStyleSheetLocation(Objects.requireNonNull(FInfoDialogWeb.class.getResource("/ru/apertum/qsystem/fx/css/scroll.css")).toString());
            } catch (Exception ex) {
                log.error(ex);
            }

            webView.setOnTouchPressed((TouchEvent event) -> refreshClockBack());
            webView.setOnMouseClicked((MouseEvent event) -> refreshClockBack());
            webView.setOnScrollStarted((ScrollEvent event) -> refreshClockBack());
            webView.setOnScrollFinished((ScrollEvent event) -> refreshClockBack());

            getChildren().add(webView);
        }

        private long lastClockBackRefresh = 0;

        private void refreshClockBack() {
            if (System.currentTimeMillis() - lastClockBackRefresh < 3000) {
                return;
            }
            if (infoDialogWeb.clockBack.isActive()) {
                infoDialogWeb.clockBack.stop();
            }
            infoDialogWeb.clockBack.start();
            lastClockBackRefresh = System.currentTimeMillis();
        }

        public void load(String url) {
            this.url = url;
            webEngine.load(url);
        }

        private String url = null;

        public void reload() {
            if (url != null) {
                Platform.runLater(() -> bro.load(url));
            }
        }

        @Override
        protected void layoutChildren() {
            layoutInArea(webView, 0, 0, getWidth(), getHeight(), 0, HPos.CENTER, VPos.CENTER);
        }

        public String goBack() {
            final WebHistory history = webEngine.getHistory();
            ObservableList<WebHistory.Entry> entryList = history.getEntries();
            int currentIndex = history.getCurrentIndex();
            if (currentIndex > 0) {
                Platform.runLater(() -> history.go(-1));
            }
            return entryList.get(currentIndex > 0 ? currentIndex - 1 : currentIndex).getUrl();
        }

        public String goForward() {
            final WebHistory history = webEngine.getHistory();
            ObservableList<WebHistory.Entry> entryList = history.getEntries();
            int currentIndex = history.getCurrentIndex();
            if (currentIndex < entryList.size() - 1) {
                Platform.runLater(() -> history.go(1));
            }
            return entryList.get(currentIndex < entryList.size() - 1 ? currentIndex + 1 : currentIndex).getUrl();
        }
    }
}
